home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / alv.sun / alv.lha / src / fconvolve.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-08  |  6.4 KB  |  277 lines

  1. #include <stdio.h>
  2. #include "defs.h"
  3.  
  4. #define DEFAULT        0
  5. #define ENHANCED    1
  6. #define MANUAL        2
  7. #define SYMMETRIC    3
  8.  
  9. ypedef struct {
  10.     float   **image;
  11.     short   xsize, ysize;
  12.     int     nflag;
  13.     float    spos, sneg;
  14. }       FILTER;
  15.  
  16. har   *progname;
  17. har   *filename;
  18. ixrect *pr1, *pr2, *tmp1;
  19. nt     scale_method;
  20. loat   scale;
  21. nt     offset;
  22. har   *filtername;
  23. hort   fcon_max_enhanced = -32768, fcon_min_enhanced = 32767;
  24. nt     mfx, mfy, newxsize, newysize;
  25. nt     levels;
  26. FILTER *filter;
  27.  
  28. #ifdef STANDALONE
  29. ain(argc, argv, envp)
  30. #else
  31. convolve_main(argc, argv, envp)
  32. #endif
  33.     int     argc;
  34.     char  **argv;
  35.     char  **envp;
  36. {
  37.     register int i, j;
  38.     FILTER *fconvolve_loadfilter();
  39.  
  40.     scale_method = DEFAULT;
  41.     scale = 1.;
  42.     offset = 0;
  43.     filtername = strsave("non-specified");
  44.     progname = strsave(argv[0]);
  45.     parse_profile(&argc, argv, envp);
  46.  
  47.     while ((gc = getopt(argc, argv, "sef:lm:M:")) != EOF)
  48.         switch (gc) {
  49.         case 's':
  50.             scale_method = SYMMETRIC;
  51.             break;
  52.         case 'e':
  53.             scale_method = ENHANCED;
  54.             break;
  55.         case 'f':
  56.             filtername = strsave(optarg);
  57.             break;
  58.         case 'l':
  59.             execlp("ls", "ls", "-C", FILTERS_DIR);
  60.             exit();
  61.             break;
  62.         case 'm':
  63.             scale_method = MANUAL;
  64.             scale = atof(optarg);
  65.             break;
  66.         case 'M':
  67.             scale_method = MANUAL;
  68.             offset = (int) atof(optarg);
  69.             break;
  70.         case '?':
  71.             errflag++;
  72.             break;
  73.         }
  74.  
  75.     if (errflag)
  76.         error((char *) 0, "Usage: %s: [-e] [-s] [-f filter] [-l] [-m manual_scale] [-M manual_offset] [infile] [outfile]", progname);
  77.  
  78.     for (stream = 0; optind < argc; stream++, optind++)
  79.         if (stream < 2 && strcmp(argv[optind], "-") != 0)
  80.             if (freopen(argv[optind], mode[stream], f[stream]) == NULL)
  81.                 error("%s %s", PR_IO_ERR_INFILE, argv[optind]);
  82.  
  83.     filter = fconvolve_loadfilter(filtername);
  84.  
  85.     if ((pr1 = pr_load(stdin, NULL)) == NULL)
  86.         error(PR_IO_ERR_RASREAD);
  87.  
  88.     if (bitrestrict)
  89.         levels = calc_max(pr1);
  90.     else
  91.         levels = MAXLEVEL(pr1->pr_depth);
  92.  
  93.     if ((pr2 = mem_create(pr1->pr_size.x, pr1->pr_size.y, pr1->pr_depth)) == NULL)
  94.         error("mem_create returned NULL");
  95.  
  96.     mfx = filter->xsize / 2;
  97.     mfy = filter->ysize / 2;
  98.  
  99.     switch (scale_method) {
  100.     case DEFAULT:
  101.         fconvolve_calc_default_scale();
  102.         fconvolve_one_pass();
  103.         break;
  104.     case ENHANCED:
  105.     case SYMMETRIC:
  106.         fconvolve_two_pass();
  107.         break;
  108.     case MANUAL:
  109.         fconvolve_one_pass();
  110.         break;
  111.     }
  112.  
  113.     pr_dump(pr2, stdout, NULL, RT_STANDARD, 0);
  114. }
  115.  
  116.  
  117. FILTER *
  118. convolve_loadfilter(name)
  119.     char   *name;
  120. {
  121.     char    buf[BUFSIZ];
  122.     FILE   *fp;
  123.     char   *ep;
  124.     FILTER *filter;
  125.     int     xsize, ysize;
  126.     float     fval;
  127.     register int i, j;
  128.     char   *getenv();
  129.  
  130.     if ((ep = getenv("FILTERS")) == NULL)
  131.         strcpy(buf, FILTERS_DIR);
  132.     else
  133.         strcpy(buf, ep);
  134.  
  135.     strcat(buf, "/");
  136.     strcat(buf, name);
  137.  
  138.     if (!(fp = fopen(buf, "r")))
  139.         error("Couldn't open filter %s", name);
  140.  
  141.     fscanf(fp, "%d %d", &xsize, &ysize);
  142.     filter = (FILTER *) malloc(sizeof(FILTER));
  143.     filter->image = (float **) dynamem(&(filter->image), sizeof(float), 2, ysize, xsize);
  144.  
  145.     filter->nflag = FALSE;
  146.     filter->xsize = xsize;
  147.     filter->ysize = ysize;
  148.  
  149.     for (j = 0; j < ysize; j++)
  150.         for (i = 0; i < xsize; i++) {
  151.             fscanf(fp, "%g", &fval);
  152.             filter->image[j][i] = fval;
  153.             if (fval < 0) {
  154.                 filter->nflag = TRUE;
  155.                 filter->sneg += fval;
  156.             } else
  157.                 filter->spos += fval;
  158.         }
  159.     filter->sneg = fabs(filter->sneg);
  160.  
  161.     return filter;
  162. }
  163. nlarge_image()
  164. {
  165.     int i,j;
  166.     newxsize = pr1->pr_size.x + mfx * 2;
  167.     newysize = pr1->pr_size.y + mfy * 2;
  168.     if ((tmp1 = mem_create(newxsize, newysize, pr1->pr_depth)) == NULL)
  169.         error("mem_create returned NULL");
  170.     
  171.     for (j = 0; j<tmp1->pr_size.y; j++)
  172.         for(i = 0; i<tmp1->pr_size.y; i++){
  173.             if(i < mfx){
  174.                 if(j < mfy)
  175.                     pr_put(tmp1, i, j, pr_get(pr1, 0, 0));
  176.                 else if(j < newysize - mfy)
  177.                     pr_put(tmp1, i, j, pr_get(pr1, 0, j-mfy));
  178.                 else
  179.                     pr_put(tmp1, i, j, pr_get(pr1, 0, pr1->pr_size.y-1));
  180.                 }
  181.             else if(i >= mfx && i < newxsize - mfx){
  182.                 if(j < filter->ysize/2)
  183.                     pr_put(tmp1, i, j, pr_get(pr1, i-mfx, 0));
  184.                 else if(j >= newysize-mfy)
  185.                     pr_put(tmp1, i, j, pr_get(pr1, i-mfx, pr1->pr_size.y-1));
  186.                 else
  187.                     pr_put(tmp1, i, j, pr_get(pr1, i-mfx, j-mfy));
  188.                 }
  189.             else {
  190.                 if(j < mfy)
  191.                     pr_put(tmp1, i, j, pr_get(pr1, pr1->pr_size.x-1, 0));
  192.                 else if(j < newysize-mfy)
  193.                     pr_put(tmp1, i, j, pr_get(pr1, pr1->pr_size.x-1, j-mfy));
  194.                 else
  195.                     pr_put(tmp1, i, j, pr_get(pr1, pr1->pr_size.x-1, pr1->pr_size.y-1));
  196.                 }
  197.             }
  198. }
  199.  
  200. convolve_calc_default_scale()
  201. {
  202.     if (filter->nflag) {
  203.         scale = 1.0 / (MAX(filter->spos, filter->sneg) * 2);
  204.         offset = levels / 2.;
  205.     } else {
  206.         scale = 1.0 / (MAX(filter->spos, filter->sneg));
  207.         offset = 0.;
  208.     }
  209. }
  210. convolve_one_pass()
  211. {
  212.     float total;
  213.     register int fj, fi;
  214.     register int i, j;
  215.  
  216.     warning("scale = %g on input, offset = %d on output", scale, offset);
  217.     
  218.     enlarge_image();
  219.  
  220.     for (j = 0; j < tmp1->pr_size.y - filter->ysize; j++)
  221.         for (i = 0; i < tmp1->pr_size.x - filter->xsize; i++) {
  222.             total = 0;
  223.             for (fj = 0; fj < filter->ysize; fj++)
  224.                 for (fi = 0; fi < filter->xsize; fi++)
  225.                     total += ((float) pr_get(tmp1, i + fi, j + fj) * filter->image[fj][fi]);
  226.             pr_put(pr2, i, j, truncate((int)rint((total * scale) + offset), levels, 0));
  227.         }
  228. }
  229.  
  230.  
  231. convolve_two_pass()
  232. {
  233.     float total, least, most;
  234.     register int fj, fi;
  235.     register int i, j;
  236.     int     tmppix;
  237.     Pixrect *tmp;
  238.     if ((tmp = mem_create(pr1->pr_size.x, pr1->pr_size.y, 32)) == NULL)
  239.         error("mem_create returned NULL");
  240.     enlarge_image();
  241.     /* first pass */
  242.     least = (2147483647.0);
  243.     most = (-2147483647.0);
  244.     for (j = 0; j <  tmp1->pr_size.y - filter->ysize; j++)
  245.         for (i = 0; i < tmp1->pr_size.x - filter->xsize; i++) {
  246.             total = 0;
  247.             for (fj = 0; fj < filter->ysize; fj++)
  248.                 for (fi = 0; fi < filter->xsize; fi++)
  249.                     total += ((float) pr_get(tmp1, i + fi, j + fj) * filter->image[fj][fi]);
  250.             pr_put(tmp, i, j, (int)rint(total));
  251.             if (total<least) least = total;
  252.             most = MAX(total, most);
  253.         }
  254.     least = fabs(least);
  255.     warning("least = %g, most = %g", least, most);
  256.     /* calculate scale and offset */
  257.     if (scale_method == SYMMETRIC) {
  258.         scale = (float) levels / MAX(least, most);
  259.         scale /= (filter->nflag) ? 2. : 1.;
  260.         offset = (filter->nflag) ? levels / 2 : 0;
  261.     } else {                /* enhanced */
  262.         scale = (float) levels / (least + most);
  263.         offset = (filter->nflag) ? least * scale : 0;
  264.     }
  265.  
  266.     warning("scale = %g on filter, output offset = %d on output", scale, offset);
  267.  
  268.     /* second pass */
  269.     for (j = 0; j < pr1->pr_size.y; j++)
  270.         for (i = 0; i < pr1->pr_size.x; i++) {
  271.             tmppix = truncate((int) ((float) pr_get(tmp, i, j) * scale + offset), levels, 0);
  272.             pr_put(pr2, i, j, tmppix);
  273.         }
  274. }
  275.  
  276.  
  277.